package geral.manager;

import geral.util.FacesUtil;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;
import javax.inject.Named;

import aspecto.annotation.Permissao;
import br.com.sgc.entities.cep.Cidade;
import br.com.sgc.entities.cep.UF;
import br.com.sgc.entities.geral.Clinica;
import br.com.sgc.entities.geral.Endereco;
import br.com.sgc.entities.geral.HorarioFuncionario;
import br.com.sgc.entities.geral.Telefone;
import br.com.sgc.entities.rh.Cargo;
import br.com.sgc.entities.rh.Funcao;
import br.com.sgc.entities.rh.Funcionario;
import br.com.sgc.entities.rh.Proventos;
import br.com.sgc.entities.seguranca.Perfil;
import br.com.sgc.entities.seguranca.Usuario;
import br.com.sgc.exception.ValidacaoException;
import br.com.sgc.permissao.Role;
import br.com.sgc.session.FuncionarioSession;

import com.encripta.EncriptaSenha;

@Named
@ConversationScoped
public class FuncionarioManager extends GenericManager implements Serializable {

	private static final long serialVersionUID = 1364584874360105825L;
	
	private Funcionario funcionario = new Funcionario();
	private List<Funcionario> funcionarios = new ArrayList<Funcionario>();
	private List<Cargo> listCargo = new ArrayList<Cargo>();
	private List<Funcao> listFuncao = new ArrayList<Funcao>();
	private List<Perfil> listPerfil = new ArrayList<Perfil>();
	private List<HorarioFuncionario> listHorario = new ArrayList<HorarioFuncionario>();
	
	
	private Boolean isCpfValido;
	
	
	@EJB private FuncionarioSession funcionarioSession;
	
	@Inject private UtilManager utilManager;

	private Boolean showPanelCadastro;
	
	@Permissao(role = Role.Sistema_RH_Funcionario_Salvar)
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public String prepareSave(){
		clear();
		showPanelCadastro = true;
		funcionario.setClinica(utilManager.getSegurancaManager().getUsuarioLogado().getClinica());
		return "formFuncionario";
	}
	
	@Permissao(role = Role.Sistema_RH_Funcionario_Salvar)
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public String save() {
		try {
			funcionario.setEnderecos(utilManager.getEnderecoManager().getEnderecoSession().prepareDependecies(utilManager.getEnderecoManager().getListEndereco(),funcionario));
			funcionario.setTelefones(utilManager.getTelefoneManager().getTelefoneSession().prepareDependecies(utilManager.getTelefoneManager().getListTelefone(),funcionario));
			funcionario.setCargo(utilManager.getCargoManager().getCargoSession().findById(Cargo.class, funcionario.getCargo().getId()));
			
			funcionario.setFuncao(utilManager.getFuncaoManager().getFuncaoSession().findById(Funcao.class, funcionario.getFuncao().getId()));
			
			funcionario.getUsuario().setSuperUsuario(false);
			funcionario.getUsuario().setSenha(EncriptaSenha.criptografa(funcionario.getUsuario().getSenha()));
			funcionario.getUsuario().setPerfilUsuario(utilManager.getPerfilManager().getPerfilSession().findById(Perfil.class, funcionario.getUsuario().getPerfilUsuario().getId()));
			funcionario.getUsuario().setClinica(utilManager.getClinicaManager().getClinicaSession().findById(Clinica.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId()));
			funcionario.setClinica(utilManager.getSegurancaManager().getUsuarioLogado().getClinica());
			
			
			funcionarioSession.save(funcionario);
			FacesUtil.mensInfo("Salvo Com Sucesso!");
			return list();
		} catch (ValidacaoException e) {
			e.printStackTrace();
			FacesUtil.mensWarn(e.getMessage());
		}
		return null;
	}
	
	@Permissao(role = Role.Sistema_RH_Funcionario_Atualizar)
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public String update() {
		try {
			funcionario.setEnderecos(utilManager.getEnderecoManager().getEnderecoSession().prepareDependecies(utilManager.getEnderecoManager().getListEndereco(),funcionario));
			funcionario.setTelefones(utilManager.getTelefoneManager().getTelefoneSession().prepareDependecies(utilManager.getTelefoneManager().getListTelefone(),funcionario));
			
			
			funcionario.setCargo(utilManager.getCargoManager().getCargoSession().findById(Cargo.class, funcionario.getCargo().getId()));
			funcionario.setFuncao(utilManager.getFuncaoManager().getFuncaoSession().findById(Funcao.class, funcionario.getFuncao().getId()));
			
			funcionario.getUsuario().setPerfilUsuario(utilManager.getPerfilManager().getPerfilSession().findById(Perfil.class, funcionario.getUsuario().getPerfilUsuario().getId()));
			funcionario.getUsuario().setClinica(utilManager.getClinicaManager().getClinicaSession().findById(Clinica.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId()));
			funcionario.getUsuario().setSuperUsuario(false);
			
			funcionarioSession.update(funcionario);
			FacesUtil.mensInfo("Atualizado Com Sucesso!");
			return list();
		} catch (ValidacaoException e) {
			e.printStackTrace();
			FacesUtil.mensWarn(e.getMessage());
		}
		return null;
	}
	
	@Permissao(role = Role.Sistema_RH_Funcionario_Excluir)
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public String delete(){
		try {
			funcionarioSession.delete(funcionario);
			FacesUtil.mensInfo("Exclu�do com Sucesso!!!");
		} catch (Exception e) {
			FacesUtil.mensInfo("Imposs�vel Excluir");
		}
		
		return list();
	}

	
	@Permissao(role = Role.Sistema_RH_Funcionario_Listar)
	public String list() {
		funcionarios = funcionarioSession.findAll(Funcionario.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
		utilManager.getEnderecoManager().setRenderPanelCadastro(false);
		utilManager.getTelefoneManager().setRenderPanelCadastro(false);
		showPanelCadastro = false;
		return "formFuncionario";
	}

	@Permissao(role = Role.Sistema_RH_Funcionario_Atualizar)
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public String prepareUpdate(){
		utilManager.getEnderecoManager().setRenderPanelCadastro(true);
		utilManager.getTelefoneManager().setRenderPanelCadastro(true);
		
		funcionario = funcionarioSession.findById(Funcionario.class, funcionario.getId(), true);
		funcionario.setClinica(utilManager.getSegurancaManager().getUsuarioLogado().getClinica());
		funcionario.setUsuario(utilManager.getSegurancaManager().getSegurancaSession().findById(Usuario.class, funcionario.getUsuario().getId(), true));
		if(funcionario.getUsuario().getPerfilUsuario() == null){
			funcionario.getUsuario().setPerfilUsuario(new Perfil());
		} else {
			funcionario.getUsuario().setPerfilUsuario(utilManager.getPerfilManager().getPerfilSession().findById(Perfil.class, funcionario.getUsuario().getPerfilUsuario().getId()));
		}
		
		funcionario.setCargo(utilManager.getCargoManager().getCargoSession().findById(Cargo.class, funcionario.getCargo().getId()));
		funcionario.setFuncao(utilManager.getFuncaoManager().getFuncaoSession().findById(Funcao.class, funcionario.getFuncao().getId()));
		
		utilManager.getEnderecoManager().getListEndereco().clear();
		utilManager.getTelefoneManager().getListTelefone().clear();
		
		funcionario.setEnderecos(utilManager.getEnderecoManager().getEnderecoSession().getEnderecosPersistent(funcionario.getEnderecos()));
		funcionario.setTelefones(utilManager.getTelefoneManager().getTelefoneSession().getTelefonesPersistent(funcionario.getTelefones()));
		
		utilManager.getEnderecoManager().getListEndereco().addAll(funcionario.getEnderecos());
		utilManager.getTelefoneManager().getListTelefone().addAll(funcionario.getTelefones());
		
		listCargo = utilManager.getCargoManager().getCargoSession().findAll(Cargo.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
		listFuncao = utilManager.getFuncaoManager().getFuncaoSession().findAll(Funcao.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
		listPerfil = utilManager.getPerfilManager().getPerfilSession().findAll(Perfil.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
		
		if(funcionario.getProventos() == null){
			funcionario.setProventos(new Proventos());
		}
		
		showPanelCadastro = true;
		isCpfValido = true;
		
		return "formFuncionario";
	}
	
	public void validateCpf() {
		try {
			isCpfValido = false;
			funcionarioSession.validarCPF(funcionario.getCpf());
			funcionario = funcionarioSession.findByCPF(funcionario.getCpf(), utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
			
			utilManager.getEnderecoManager().setRenderPanelLogradouro(false);
			utilManager.getEnderecoManager().setListCidade(new ArrayList<Cidade>());
			utilManager.getEnderecoManager().setListUF(new ArrayList<UF>());
			utilManager.getEnderecoManager().setRenderPanelCadastro(true);
			utilManager.getTelefoneManager().setRenderPanelCadastro(true);
			
			utilManager.getTelefoneManager().getListTelefone().clear();
			utilManager.getTelefoneManager().setTelefone(new Telefone());
			
			utilManager.getEnderecoManager().setEndereco(new Endereco());
			utilManager.getEnderecoManager().getListEndereco().clear();
			
			utilManager.getEnderecoManager().setListEndereco(funcionario.getEnderecos());
			utilManager.getTelefoneManager().setListTelefone(funcionario.getTelefones());
			
			isCpfValido = true;

		} catch (ValidacaoException e) {
			FacesUtil.mensWarn(e.getMessage());
		}
	}
	
	public void clear(){
		utilManager.getEnderecoManager().setRenderPanelLogradouro(false);
		utilManager.getEnderecoManager().setListCidade(new ArrayList<Cidade>());
		utilManager.getEnderecoManager().setListUF(new ArrayList<UF>());
		utilManager.getEnderecoManager().setRenderPanelCadastro(true);
		utilManager.getTelefoneManager().setRenderPanelCadastro(true);
		
		utilManager.getTelefoneManager().getListTelefone().clear();
		utilManager.getTelefoneManager().setTelefone(new Telefone());
		
		utilManager.getEnderecoManager().setEndereco(new Endereco());
		utilManager.getEnderecoManager().getListEndereco().clear();
		
		listCargo = utilManager.getCargoManager().getCargoSession().findAll(Cargo.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
		listFuncao = utilManager.getFuncaoManager().getFuncaoSession().findAll(Funcao.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
		listPerfil = utilManager.getPerfilManager().getPerfilSession().findAll(Perfil.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
		listHorario = utilManager.getHorarioManager().getHorarioSession().findAll(HorarioFuncionario.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
		
		funcionario = new Funcionario();
		funcionario.setAtivo(true);
		funcionario.setHorarioFuncionario(new HorarioFuncionario());
		isCpfValido = false;
	}
	
	
	public void calcularCusto(){
		BigDecimal custo = funcionario.getProventos().getSalarioBase();
		
		BigDecimal valeRefeicao = funcionario.getProventos().getValorValeRefeicao();
		if(valeRefeicao == null){
			valeRefeicao = new BigDecimal(0.0);
		}

		BigDecimal percentFGTS = funcionario.getProventos().getPercentualFGTS();
		if(percentFGTS == null){
			percentFGTS = new BigDecimal(0.0);
		}
		
		// Calcular Percentual FGTS
		BigDecimal fgts = custo.multiply(percentFGTS).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
		
		BigDecimal percentINSS = funcionario.getProventos().getPercentualINSS();
		if(percentINSS == null){
			percentINSS = new BigDecimal(0.0);
		}
		
		// Calcular Percentual INSS
		BigDecimal inss = custo.multiply(percentINSS).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
		
		// Calcular Vale Transporte
		BigDecimal VR = funcionario.getProventos().getValorValeTransporte();
		if(VR == null){
			VR = new BigDecimal(0.0);
		}
		
		BigDecimal percentVR = funcionario.getProventos().getPercentualDescontoValeTransporte();
		if(percentVR == null){
			percentVR = new BigDecimal(0.0);
		}
		
		BigDecimal descontoVR = custo.multiply(percentVR).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
		if(descontoVR.doubleValue() > VR.doubleValue()){
			descontoVR = VR;
		}
		
		// Calcular Previsão Férias
		BigDecimal ferias = custo.divide(new BigDecimal(12), 2, RoundingMode.HALF_UP);
		BigDecimal ferias13 = custo.divide(new BigDecimal(36), 2, RoundingMode.HALF_UP);
		
		// Calcular Previsãp 13º
		BigDecimal decimoTerceiro = custo.divide(new BigDecimal(12), 2, RoundingMode.HALF_UP);
		BigDecimal custoFeriasDecimo = ferias.add(ferias13).add(decimoTerceiro);
		
		
		BigDecimal inssSobreFeriasDecimo = custoFeriasDecimo.multiply(percentINSS).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
		BigDecimal fgtsSobreFeriasDecimo = custoFeriasDecimo.multiply(percentFGTS).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP); 
		
		BigDecimal custoTotal = custo.add(fgts).add(inss).add(VR).add(valeRefeicao).add(custoFeriasDecimo).add(inssSobreFeriasDecimo).add(fgtsSobreFeriasDecimo).subtract(descontoVR);
		custoTotal.setScale(2, RoundingMode.HALF_UP);
		
		funcionario.getProventos().setCustoEfetivoTotal(custoTotal);
		funcionario.getProventos().setCustoEfetivoTotalHora(custoTotal.divide(new BigDecimal(funcionario.getProventos().getTotalHorasMensal()), 2, RoundingMode.HALF_UP));
		
	}

	public Funcionario getFuncionario() {
		return funcionario;
	}

	public void setFuncionario(Funcionario funcionario) {
		this.funcionario = funcionario;
	}

	public List<Funcionario> getFuncionarios() {
		return funcionarios;
	}

	public void setFuncionarios(List<Funcionario> funcionarios) {
		this.funcionarios = funcionarios;
	}

	public Boolean getIsCpfValido() {
		return isCpfValido;
	}

	public void setIsCpfValido(Boolean isCpfValido) {
		this.isCpfValido = isCpfValido;
	}

	public FuncionarioSession getFuncionarioSession() {
		return funcionarioSession;
	}

	public void setFuncionarioSession(FuncionarioSession funcionarioSession) {
		this.funcionarioSession = funcionarioSession;
	}

	public Boolean getShowPanelCadastro() {
		return showPanelCadastro;
	}

	public void setShowPanelCadastro(Boolean showPanelCadastro) {
		this.showPanelCadastro = showPanelCadastro;
	}

	public List<Cargo> getListCargo() {
		return listCargo;
	}

	public void setListCargo(List<Cargo> listCargo) {
		this.listCargo = listCargo;
	}

	public List<Funcao> getListFuncao() {
		return listFuncao;
	}

	public void setListFuncao(List<Funcao> listFuncao) {
		this.listFuncao = listFuncao;
	}

	public List<Perfil> getListPerfil() {
		return listPerfil;
	}

	public void setListPerfil(List<Perfil> listPerfil) {
		this.listPerfil = listPerfil;
	}

	public List<HorarioFuncionario> getListHorario() {
		return listHorario;
	}

	public void setListHorario(List<HorarioFuncionario> listHorario) {
		this.listHorario = listHorario;
	}
	
}
